package com.taskflow.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.taskflow.entity.EntryData;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.springframework.http.*;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.SSLContext;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 外部API调用服务
 */
@Slf4j
@Service
public class ExternalApiService {

    private static final String API_URL = "https://szwm.albsc.com/prod-api/admin-api/entry/bill/findGdxx";
    private static final String AES_KEY = "alunba@2025qswde";

    private final RestTemplate restTemplate;

    public ExternalApiService() {
        this.restTemplate = createRestTemplate();
    }

    /**
     * 创建忽略SSL证书验证的RestTemplate
     */
    private RestTemplate createRestTemplate() {
        try {
            SSLContext sslContext = SSLContextBuilder.create()
                    .loadTrustMaterial((X509Certificate[] chain, String authType) -> true)
                    .build();

            SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
                    sslContext,
                    NoopHostnameVerifier.INSTANCE
            );

            CloseableHttpClient httpClient = HttpClients.custom()
                    .setSSLSocketFactory(socketFactory)
                    .build();

            HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
            factory.setConnectTimeout(30000);
            factory.setReadTimeout(30000);

            return new RestTemplate(factory);
        } catch (Exception e) {
            log.error("创建RestTemplate失败，使用默认配置", e);
            return new RestTemplate();
        }
    }

    /**
     * 查询关单数据
     * @param companyTaxNo 企业税号
     * @param declareDateRange 申报日期范围（天数）
     * @return 关单数据列表
     */
    public List<EntryData> queryEntryData(String companyTaxNo, Integer declareDateRange) {
        try {
            // 计算日期范围
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Calendar calendar = Calendar.getInstance();
            String ckrqz = sdf.format(calendar.getTime()); // 结束日期（今天）

            // 往前推 N 天
            if (declareDateRange != null && declareDateRange > 0) {
                calendar.add(Calendar.DAY_OF_MONTH, -declareDateRange);
            } else {
                calendar.add(Calendar.DAY_OF_MONTH, -1); // 默认前1天
            }
            String ckrqq = sdf.format(calendar.getTime()); // 开始日期

            // 构建请求报文
            Map<String, String> requestData = new HashMap<>();
            requestData.put("nsrsbh", companyTaxNo);
            requestData.put("sbrqq", ckrqq);
            requestData.put("sbrqz", ckrqz);

          //  log.info("查询关单数据请求参数: {}", requestData);

            // 1. 转JSON字符串
            String jsonStr = JSON.toJSONString(requestData);
            log.info("查询关单数据请求参数jsonStr: {}", jsonStr);
            // 2. BASE64编码
            String base64Encoded = Base64.getEncoder().encodeToString(jsonStr.getBytes(StandardCharsets.UTF_8));
            log.debug("BASE64编码后: {}", base64Encoded);

            // 3. AES加密
            String encrypted = aesEncrypt(base64Encoded, AES_KEY);
            log.debug("AES加密后: {}", encrypted);

            // 4. 发送HTTP请求
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);

            // 按对方接口要求，直接发送加密串为请求体（非 {"data":...} 的JSON）
            HttpEntity<String> entity = new HttpEntity<>(encrypted, headers);

            ResponseEntity<String> response = restTemplate.exchange(
                    API_URL,
                    HttpMethod.POST,
                    entity,
                    String.class
            );

            log.info("外部API响应状态: {}", response.getStatusCode());

            // 5. 解析响应
            if (response.getStatusCode() == HttpStatus.OK) {
                String responseBody = response.getBody();
                log.debug("外部API响应内容: {}", responseBody);

                return parseResponse(responseBody);
            } else {
                log.error("外部API调用失败，状态码: {}", response.getStatusCode());
                throw new IllegalStateException("外部API状态码: " + response.getStatusCode());
            }

        } catch (Exception e) {
            log.error("调用外部API查询关单数据失败", e);
            throw new RuntimeException("外部API调用失败: " + e.getMessage(), e);
        }
    }

    /**
     * 查询关单数据（按具体日期范围）
     * @param companyTaxNo 企业税号
     * @param startDate 开始日期 yyyyMMdd
     * @param endDate 结束日期 yyyyMMdd
     * @return 关单数据列表
     */
    public List<EntryData> queryEntryDataByDateRange(String companyTaxNo, String startDate, String endDate) {
        try {
            // 转换日期格式：yyyyMMdd -> yyyy-MM-dd
            String ckrqq = startDate.substring(0, 4) + "-" + startDate.substring(4, 6) + "-" + startDate.substring(6, 8);
            String ckrqz = endDate.substring(0, 4) + "-" + endDate.substring(4, 6) + "-" + endDate.substring(6, 8);

            // 构建请求报文
            Map<String, String> requestData = new HashMap<>();
            requestData.put("nsrsbh", companyTaxNo);
            requestData.put("sbrqq", ckrqq);
            requestData.put("sbrqz", ckrqz);

            log.info("查询关单数据（日期范围）请求参数: {}", requestData);

            // 1. 转JSON字符串
            String jsonStr = JSON.toJSONString(requestData);

            // 2. BASE64编码
            String base64Encoded = Base64.getEncoder().encodeToString(jsonStr.getBytes(StandardCharsets.UTF_8));

            // 3. AES加密
            String encrypted = aesEncrypt(base64Encoded, AES_KEY);
            log.debug("AES加密后: {}", encrypted);

            // 4. 发送HTTP请求
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<String> entity = new HttpEntity<>(encrypted, headers);

            ResponseEntity<String> response = restTemplate.exchange(
                    API_URL,
                    HttpMethod.POST,
                    entity,
                    String.class
            );

            log.info("外部API响应状态码: {}", response.getStatusCode());
            log.info("外部API响应内容: {}", response.getBody());

            // 解析响应
            if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
                return parseResponse(response.getBody());
            } else {
                throw new IllegalStateException("外部API状态码: " + response.getStatusCode());
            }

        } catch (Exception e) {
            log.error("调用外部API查询关单数据（日期范围）失败", e);
            throw new RuntimeException("外部API调用失败: " + e.getMessage(), e);
        }
    }

    /**
     * AES加密
     */
    private String aesEncrypt(String content, String key) throws Exception {
        // 确保密钥长度为16字节
        byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
        if (keyBytes.length != 16) {
            keyBytes = Arrays.copyOf(keyBytes, 16);
        }

        SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);

        byte[] encrypted = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encrypted);
    }

    /**
     * AES解密
     */
    private String aesDecrypt(String encrypted, String key) throws Exception {
        // 确保密钥长度为16字节
        byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
        if (keyBytes.length != 16) {
            keyBytes = Arrays.copyOf(keyBytes, 16);
        }

        SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);

        byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encrypted));
        return new String(decrypted, StandardCharsets.UTF_8);
    }

    /**
     * 解析API响应数据
     */
    private List<EntryData> parseResponse(String responseBody) {
        List<EntryData> result = new ArrayList<>();

        try {
            JSONObject jsonObject = JSON.parseObject(responseBody);

            Integer code = jsonObject.getInteger("code");
            if (code == null || code != 0) {
                String msg = jsonObject.getString("msg");
                log.error("API返回错误: {}", msg);
                throw new IllegalStateException("API错误: " + msg);
            }

            // 解析数据
            Object data = jsonObject.get("data");
            if (data == null) {
                // 成功但无数据
                return result;
            }

            // 如果data是加密的，需要解密
            if (data instanceof String) {
                String decrypted = aesDecrypt((String) data, AES_KEY);
                String base64Decoded = new String(Base64.getDecoder().decode(decrypted), StandardCharsets.UTF_8);
                data = JSON.parse(base64Decoded);
            }

            // 解析为数组
            JSONArray dataArray;
            if (data instanceof JSONArray) {
                dataArray = (JSONArray) data;
            } else if (data instanceof JSONObject) {
                // 如果是对象，尝试获取其中的list字段
                JSONObject dataObj = (JSONObject) data;
                dataArray = dataObj.getJSONArray("list");
                if (dataArray == null) {
                    dataArray = dataObj.getJSONArray("records");
                }
                if (dataArray == null) {
                    // 成功但未提供列表字段
                    return result;
                }
            } else {
                log.warn("不支持的数据格式: {}", data.getClass());
                return result;
            }

            // 每条单据包含一个明细数组（entryDetailDOList / entryDetailVOList）
            for (int i = 0; i < dataArray.size(); i++) {
                JSONObject head = dataArray.getJSONObject(i);
                JSONArray detailList = head.getJSONArray("entryDetailDOList");
                if (detailList == null) {
                    detailList = head.getJSONArray("entryDetailVOList");
                }
                if (detailList == null || detailList.isEmpty()) {
                    // 没有明细，按抬头存一行
                    EntryData single = convertToEntryData(head, null);
                    if (single != null) {
                        result.add(single);
                    }
                    continue;
                }

                // 循环处理每条明细
                log.debug("报关单 {} 包含 {} 条明细", head.getString("entryId"), detailList.size());
                for (int j = 0; j < detailList.size(); j++) {
                    JSONObject detail = detailList.getJSONObject(j);
                    EntryData row = convertToEntryData(head, detail);
                    if (row != null) {
                        result.add(row);
                        log.debug("解析明细 {}/{}: entryId={}, gNo={}", j+1, detailList.size(),
                                row.getEntryId(), row.getGNo());
                    }
                }
            }

            log.info("成功解析关单数据 {} 条", result.size());

        } catch (Exception e) {
            log.error("解析API响应失败", e);
            throw new RuntimeException("解析API响应失败: " + e.getMessage(), e);
        }

        return result;
    }

    /**
     * 将JSON对象转换为EntryData实体
     */
    private EntryData convertToEntryData(JSONObject head, JSONObject detail) {
        try {
            EntryData entryData = new EntryData();

            // 抬头字段
            entryData.setPreEntryId(any(head, "preEntryId", "PRE_ENTRY_ID"));
            entryData.setEntryId(any(head, "entryId", "ENTRY_ID", "seqNo"));
            entryData.setSeqNo(any(head, "seqNo", "SEQ_NO"));
            
            entryData.setCustomMaster(any(head, "customMaster", "CUSTOM_MASTER"));
            entryData.setCustomMasterName(any(head, "customMasterName", "CUSTOM_MASTER_NAME"));
            entryData.setTradeCo(any(head, "tradeCo", "TRADE_CO"));
            entryData.setTradeName(any(head, "tradeName", "TRADE_NAME"));
            entryData.setTradeCoScc(any(head, "tradeCoScc", "TRADE_CO_SCC"));
            
            entryData.setIePort(any(head, "iePort", "IE_PORT", "iEPort"));
            entryData.setIePortName(any(head, "iePortName", "IE_PORT_NAME", "iEPortName"));
            entryData.setIeDate(any(head, "ieDate", "IE_DATE", "iEDate"));
            entryData.setDDate(any(head, "dDate", "D_DATE", "ddate"));
            
            entryData.setManualNo(any(head, "manualNo", "MANUAL_NO"));
            entryData.setOverseasConsigneeCode(any(head, "overseasConsigneeCode", "OVERSEAS_CONSIGNEE_CODE"));
            entryData.setOverseasConsigneeEname(any(head, "overseasConsigneeEname", "OVERSEAS_CONSIGNEE_ENAME"));
            
            entryData.setTrafMode(any(head, "trafMode", "TRAF_MODE"));
            entryData.setTrafModeName(any(head, "trafModeName", "TRAF_MODE_NAME"));
            entryData.setTrafName(any(head, "trafName", "TRAF_NAME"));
            entryData.setVoyageNo(any(head, "voyageNo", "VOYAGE_NO"));
            entryData.setBillNo(any(head, "billNo", "BILL_NO"));
            
            entryData.setOwnerCode(any(head, "ownerCode", "OWNER_CODE"));
            entryData.setOwnerName(any(head, "ownerName", "OWNER_NAME"));
            entryData.setOwnerCodeScc(any(head, "ownerCodeScc", "OWNER_CODE_SCC"));
            
            entryData.setTradeMode(any(head, "tradeMode", "TRADE_MODE"));
            entryData.setTradeModeName(any(head, "tradeModeName", "TRADE_MODE_NAME"));
            entryData.setCutMode(any(head, "cutMode", "CUT_MODE"));
            entryData.setCutName(any(head, "cutName", "CUT_NAME"));
            
            entryData.setLicenseNo(any(head, "licenseNo", "LICENSE_NO"));
            entryData.setContrNo(any(head, "contrNo", "CONTR_NO"));
            
            entryData.setTradeAreaCode(any(head, "tradeAreaCode", "TRADE_AREA_CODE"));
            entryData.setTradeAreaName(any(head, "tradeAreaName", "TRADE_AREA_NAME"));
            entryData.setTradeCountry(any(head, "tradeCountry", "TRADE_COUNTRY"));
            entryData.setTradeCountryName(any(head, "tradeCountryName", "TRADE_COUNTRY_NAME"));
            
            entryData.setDistinatePort(any(head, "distinatePort", "DISTINATE_PORT"));
            entryData.setDistinatePortName(any(head, "distinatePortName", "DISTINATE_PORT_NAME"));
            entryData.setEntryPortCode(any(head, "cusfie", "ENTRY_PORT_CODE"));
            entryData.setEntryPortName(any(head, "entryPortName", "ENTRY_PORT_NAME"));
            entryData.setDistrictCode(any(head, "districtCode", "DISTRICT_CODE"));
            entryData.setWrapType(any(head, "wrapType", "WRAP_TYPE"));
            entryData.setWrapTypeName(any(head, "wrapTypeName", "WRAP_TYPE_NAME"));
            entryData.setPackNo(any(head, "packNo", "PACK_NO"));
            entryData.setNetWt(any(head, "netWt", "NET_WT"));
            entryData.setGrossWt(any(head, "grossWt", "GROSS_WT"));
            
            entryData.setTransMode(any(head, "transMode", "TRANS_MODE"));
            entryData.setTransModeName(any(head, "transModeName", "TRANS_MODE_NAME"));
            
            // 运费相关字段（需要拼接）
            entryData.setFeeCurr(any(head, "feeCurr", "FEE_CURR"));
            entryData.setFeeRate(any(head, "feeRate", "FEE_RATE"));
            entryData.setFeeMark(any(head, "feeMark", "FEE_MARK"));
            
            // 保费相关字段（需要拼接）
            entryData.setInsurCurr(any(head, "insurCurr", "INSUR_CURR"));
            entryData.setInsurRate(any(head, "insurRate", "INSUR_RATE"));
            entryData.setInsurMark(any(head, "insurMark", "INSUR_MARK"));
            
            // 杂费相关字段（需要拼接）
            entryData.setOtherCurr(any(head, "otherCurr", "OTHER_CURR"));
            entryData.setOtherRate(any(head, "otherRate", "OTHER_RATE"));
            entryData.setOtherMark(any(head, "otherMark", "OTHER_MARK"));
            
            entryData.setCertMark(any(head, "certMark", "CERT_MARK"));
            entryData.setNoteS(any(head, "noteS", "NOTE_S", "notes"));
            
            entryData.setAgentCode(any(head, "agentCode", "AGENT_CODE"));
            entryData.setAgentName(any(head, "agentName", "AGENT_NAME"));
            entryData.setAgentCodeScc(any(head, "agentCodeScc", "AGENT_CODE_SCC"));
            
            entryData.setPromiseMark1(any(head, "promiseMark1", "PROMISE_MARK_1"));
            entryData.setPromiseMark2(any(head, "promiseMark2", "PROMISE_MARK_2"));
            entryData.setPromiseMark3(any(head, "promiseMark3", "PROMISE_MARK_3"));


            // 明细字段（如存在）
            if (detail != null) {
                entryData.setGNo(any(detail, "gNo", "G_NO"));
                entryData.setCodeTS(any(detail, "codeT", "CODE_TS"));
                entryData.setGModel(any(detail, "gModel", "G_MODEL"));
                entryData.setGName(any(detail, "gName", "G_NAME"));
                entryData.setQty(any(detail, "gQty", "G_QTY"));
                entryData.setQtyUnit(any(detail, "gUnit", "G_UNIT"));
                entryData.setQty1(any(detail, "qty1", "QTY_1"));
                entryData.setQty1Unit(any(detail, "unit1", "UNIT_1"));
                entryData.setQty2(any(detail, "qty2", "QTY_2"));
                entryData.setQty2Unit(any(detail, "unit2", "UNIT_2"));
                entryData.setDeclPrice(any(detail, "declPrice", "DECL_PRICE"));
                entryData.setDeclTotal(any(detail, "declTotal", "DECL_TOTAL"));
                entryData.setTradeCurr(any(detail, "tradeCurr", "TRADE_CURR"));
                entryData.setOriginCountry(any(detail, "originCountry", "ORIGIN_COUNTRY"));
                entryData.setDestinationCountry(any(detail, "destinationCountry", "DESTINATION_COUNTRY"));
                entryData.setDutyMode(any(detail, "dutyMode", "DUTY_MODE"));
            }

            // 必填字段检查
            if (entryData.getEntryId() == null || entryData.getEntryId().trim().isEmpty()) {
                log.warn("关单数据缺少entryId，跳过");
                return null;
            }

            return entryData;

        } catch (Exception e) {
            log.error("转换EntryData失败", e);
            return null;
        }
    }

    private String any(JSONObject json, String... keys) {
        for (String k : keys) {
            String v = json.getString(k);
            if (v != null && v.trim().length() > 0) return v;
        }
        return null;
    }
}

